package com.dkd.flow.rules.conditions;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.dkd.flow.emums.RuleType;
import com.dkd.flow.rules.BaseRules;
import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Rule(name = "ConditionsRule", description = "其他字段条件规则", priority = 1)
public class ConditionsRule {
    private static final Logger log = LoggerFactory.getLogger(ConditionsRule.class);
    @Autowired
    BaseRules baseRules;
    JSONArray conditions = null;
    JSONObject properties = null;
    JSONObject node = null;
    // 日期格式
    private static final String DATE_FORMAT = "yyyy-MM-dd";
    // 时间格式
    private static final String TIME_FORMAT = "HH:mm:ss";
    void clear() {
        node = null;
        conditions = null;
        properties = null;
    }
    @Condition
    public boolean condition(@Fact("node") JSONObject node) {
        this.clear();
        this.node = node;
        getConditions();
        return conditions != null && conditions.size() > 0;
    }
    @Action
    public void action() {
        JSONObject formData = baseRules.formData;
        List<JSONObject> conditionsList = conditions.stream()
                .map(m -> (JSONObject) m)
                .collect(Collectors.toList());
        boolean allConditionsMet = true;
        for (JSONObject jsonItem : conditionsList) {
            String vModel = jsonItem.getString("vModel");
            if (!formData.containsKey(vModel)) {
                allConditionsMet = false;
                printMismatchInfo(jsonItem,
                        formData);
                break;
            }
            ExpressionParser parser = new SpelExpressionParser();
            StandardEvaluationContext context = new StandardEvaluationContext();
            context.setVariable("formData",
                    formData);
            context.setVariable("jsonItem",
                    jsonItem);
            String spelExpression;
            // 根据node的tag进行分类处理
            String tag = jsonItem.getJSONObject("node")
                    .getString("tag");
            switch (tag) {
                case "el-date-picker":
                case "el-time-picker":
                    spelExpression = handleDateOrTimeCondition(jsonItem);
                    break;
                case "el-input-number":
                case "fc-amount":
                    spelExpression = handleNumericCondition(jsonItem);
                    break;
                case "el-select":
                case "el-radio-group":
                case "el-checkbox-group":
                case "fc-liable-user-select":
                case "fc-user-select":
                case "fc-dept-select":
                case "fc-role-select":
                case "fc-target-dept-select":
                    spelExpression = handleSelectOrRadioOrCheckboxCondition(jsonItem,
                            formData);
                    break;
                case "el-input":
                    spelExpression = handleInputCondition(jsonItem);
                    break;
                default:
                    throw new IllegalArgumentException("不支持的比较类型: " + tag);
            }
            // 输出 SpEL 表达式进行调试
            log.debug("Generated SpEL expression----------> {}",
                    spelExpression);
            try {
                boolean conditionResult = parser.parseExpression(spelExpression)
                        .getValue(context,
                                Boolean.class);
                if (!conditionResult) {
                    allConditionsMet = false;
                    printMismatchInfo(jsonItem,
                            formData);
                    break;
                }

            } catch (Exception e) {
                log.error("解析SpEL表达式时出错: {}",
                        e.getMessage());
                allConditionsMet = false;
                printMismatchInfo(jsonItem,
                        formData);
                break;
            }
        }
        setResult(allConditionsMet);
    }
    private String handleNumericCondition(JSONObject jsonItem) {
        //String vModel = jsonItem.getString("vModel");
        JSONObject conditionValueObj = jsonItem.getJSONObject("conditionValue");
        Object value = conditionValueObj.get("value");
        String conditionType = conditionValueObj.getString("type");
        String operator = getOperator(conditionType);
        if (value instanceof JSONArray) {
            JSONArray valueArray = (JSONArray) value;
            Object lowerBound = valueArray.get(0);
            String lowerOperator = valueArray.getString(1);
            String upperOperator = valueArray.getString(2);
            Object upperBound = valueArray.get(3);
            String lowerSpelOperator = getOperatorFromSymbol(lowerOperator);
            String upperSpelOperator = getOperatorFromSymbol(upperOperator);
            String lowerExpression = String.format("%s %s #formData[#jsonItem['vModel']]",
                    lowerBound,
                    lowerSpelOperator);
            String upperExpression = String.format("#formData[#jsonItem['vModel']] %s %s",
                    upperSpelOperator,
                    upperBound);
            return lowerExpression + " && " + upperExpression;
        } else {
            return String.format("#formData[#jsonItem['vModel']] %s %s",
                    operator,
                    value);
        }
    }
    private String handleDateOrTimeCondition(JSONObject jsonItem) {
        String vModel = jsonItem.getString("vModel");
        JSONObject conditionValueObj = jsonItem.getJSONObject("conditionValue");
        Object value = conditionValueObj.get("value");
        String conditionType = conditionValueObj.getString("type");
        String operator = getOperator(conditionType);
        String dateOrTimeFormat;
        if ("el-date-picker".equals(jsonItem.getJSONObject("node")
                .getString("tag"))) {
            dateOrTimeFormat = DATE_FORMAT;
        } else {
            dateOrTimeFormat = TIME_FORMAT;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(dateOrTimeFormat);
        JSONObject formData = baseRules.formData;
        Object formValueObj = formData.get(vModel);
        if (formValueObj == null) {
            log.error("表单中未找到对应的日期值，vModel: {}",
                    vModel);
            throw new IllegalArgumentException("表单中未找到对应的日期值");
        }
        try {
            Date formDate = sdf.parse(formValueObj.toString());
            if (value instanceof JSONArray) {
                JSONArray valueArray = (JSONArray) value;
                Object lowerBound = valueArray.get(0);
                Object upperBound = valueArray.get(3);
                Date lowerDate = sdf.parse(lowerBound.toString());
                Date upperDate = sdf.parse(upperBound.toString());
                String lowerOperator = valueArray.getString(1);
                String upperOperator = valueArray.getString(2);
                String lowerSpelOperator = getOperatorFromSymbol(lowerOperator);
                String upperSpelOperator = getOperatorFromSymbol(upperOperator);
                // 使用时间戳进行比较，并明确指定为 long 类型
                String lowerExpression = String.format("%dL %s %dL",
                        lowerDate.getTime(),
                        lowerSpelOperator,
                        formDate.getTime());
                String upperExpression = String.format("%dL %s %dL",
                        formDate.getTime(),
                        upperSpelOperator,
                        upperDate.getTime());
                log.debug("Generated SpEL expression for lower bound: {}",
                        lowerExpression);
                log.debug("Generated SpEL expression for upper bound: {}",
                        upperExpression);
                return lowerExpression + " && " + upperExpression;
            } else {
                Date conditionDate = sdf.parse(value.toString());
                // 使用时间戳进行比较，并明确指定为 long 类型
                String result = String.format("%dL %s %dL",
                        formDate.getTime(),
                        operator,
                        conditionDate.getTime());
                log.debug("Generated SpEL expression: {}",
                        result);
                return result;
            }
        } catch (ParseException e) {
            log.error("日期或时间解析错误: {}",
                    e.getMessage());
            throw new IllegalArgumentException("日期或时间解析错误");
        }
    }
    private String handleSelectOrRadioOrCheckboxCondition(JSONObject jsonItem, JSONObject formData) {
        String vModel = jsonItem.getString("vModel");
        JSONArray conditionValueArray = jsonItem.getJSONArray("conditionValue");
        List<String> allowedValues = conditionValueArray.stream()
                .map(item -> ((JSONObject) item).getString("value"))
                .collect(Collectors.toList());
        Object formValue = getFormValue(formData,
                vModel);
        if (formValue instanceof JSONArray) {
            JSONArray formValueArray = (JSONArray) formValue;
            boolean hasMatch = false;
            for (int i = 0; i < formValueArray.size(); i++) {
                JSONObject formValueObj = formValueArray.getJSONObject(i);
                String formValueStr = formValueObj.getString("value");
                if (allowedValues.contains(formValueStr)) {
                    hasMatch = true;
                    break;
                }
            }
            return String.valueOf(hasMatch);
        } else if (formValue instanceof String) {
            return String.valueOf(allowedValues.contains(formValue));
        }
        return "false";
    }
    private String handleInputCondition(JSONObject jsonItem) {
        String vModel = jsonItem.getString("vModel");
        Object conditionValue = getMatchConditions(jsonItem);
        String conditionType = jsonItem.getString("conditionType");
        String operator = getOperator(conditionType);
        if (conditionValue instanceof String) {
            return String.format("#formData[#jsonItem['vModel']] %s '%s'",
                    operator,
                    conditionValue);
        } else {
            return String.format("#formData[#jsonItem['vModel']] %s %s",
                    operator,
                    conditionValue);
        }
    }
    private Object getMatchConditions(JSONObject jsonItem) {
        Object conditionValue = jsonItem.get("conditionValue");
        if (conditionValue instanceof String) {
            try {
                return Integer.parseInt((String) conditionValue);
            } catch (NumberFormatException e) {
                // 如果无法转换为数字，保持原字符串类型
                return conditionValue;
            }
        }
        return conditionValue;
    }
    private Object getFormValue(JSONObject formData, String vModel) {
        Object formValue = formData.get(vModel);
        if (formValue instanceof JSONArray && ((JSONArray) formValue).size() == 1) {
            JSONObject singleValueObj = ((JSONArray) formValue).getJSONObject(0);
            if (singleValueObj != null) {
                return singleValueObj.getString("value");
            }
        }
        return formValue;
    }
    private String getOperator(String conditionType) {
        switch (conditionType) {
            case "gt":
                return ">";
            case "gte":
                return ">=";
            case "lt":
                return "<";
            case "lte":
                return "<=";
            case "eq":
                return "==";
            case "neq":
                return "!=";
            case "bet":
                // 这里返回空字符串，因为范围比较不需要单一操作符
                return "";
            default:
                throw new IllegalArgumentException("不支持的比较类型: " + conditionType);
        }
    }
    private String getOperatorFromSymbol(String symbol) {
        switch (symbol) {
            case "lt":
                return "<";
            case "lte":
                return "<=";
            case "gt":
                return ">";
            case "gte":
                return ">=";
            default:
                throw new IllegalArgumentException("不支持的操作符符号: " + symbol);
        }
    }
    void getConditions() {
        properties = node.getJSONObject("properties");
        if (!properties.isEmpty()) {
            conditions = properties.getJSONArray(RuleType.CONDITIONS_RULE.value);
        }
    }
    void setResult(Boolean bool) {
        JSONObject fieldDataRule = new JSONObject();
        fieldDataRule.put("result",
                bool);
        fieldDataRule.put("nodeId",
                node.getString("nodeId"));
        fieldDataRule.put("ruleType",
                RuleType.CONDITIONS_RULE.value);
        fieldDataRule.put("ruleTypeName",
                RuleType.CONDITIONS_RULE.name);
        fieldDataRule.put("priority",
                properties.getIntValue("priority"));
        baseRules.ruleResult.add(fieldDataRule);
    }
    private void printMismatchInfo(JSONObject jsonItem, JSONObject formData) {
        String tag = jsonItem.getJSONObject("node")
                .getString("tag");
        String vModel = jsonItem.getString("vModel");
        Object formValue = getFormValue(formData,
                vModel);
        System.out.println("允许的tag:----------> " + tag);
        System.out.println("条件设置里的条件label:---------->" + jsonItem.getString("label"));
        System.out.println("条件设置里的条件:---------->" + jsonItem.toJSONString());
        System.out.println("表单提交的值:---------->" + formValue);
    }
}